package io.github.source.media.bean;

import com.github.catvod.crawler.Spider;
import com.github.catvod.crawler.SpiderDebug;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Json;
import com.github.catvod.utils.Trans;
import com.github.catvod.utils.Util;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.orhanobut.hawk.Hawk;
import com.orhanobut.logger.Logger;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

import androidx.annotation.NonNull;
import androidx.collection.ArrayMap;
import io.github.source.Init;
import io.github.source.bean.Site;
import io.github.source.config.VodConfig;
import okhttp3.Call;
import okhttp3.Response;

/**
 * @ClassName: MediaQueryProvider
 * @Description: TODO(查询)
 * @author: huangrongcai
 * @date: 2024/6/21
 * @Copyright: 黄嵘才（HuangRc)
 */
interface MediaQueryProvider {
    /**
     * 获取媒体列表。
     *
     * @param query 查询选项，包含过滤条件等。
     * @return 包含媒体列表的MediaResult对象，永远不会为null。
     */
    @NonNull
    MediaResult<List<MediaBean>> getMediaList(MediaQuery query) throws Exception;

    interface Factory {
        MediaQueryProvider newCall(MediaQuery query);
    }

    static MediaQueryProvider create() {
        return new MediaQueryProvider.Impl();
    }

    /**
     * @ClassName: MediaQueryProviderImpl
     * @Description: (搜索 查询)影影源 返回MediaResult
     * @Version: 1.0
     * @author: huangrongcai
     * @date: 2024/6/21
     * @Copyright: 黄嵘才（HuangRc)
     */
    class Impl implements MediaQueryProvider {
        private static final String TAG = "Source.Media.Query.Provider.MediaQuery";

        @NonNull
        @Override
        public MediaResult<List<MediaBean>> getMediaList(MediaQuery query) {

            if (query == null) {
                throw new IllegalArgumentException("MediaQuery cannot be null.");
            }
            loggerOnQuery(VodConfig.get().getSite(query.getSiteKey()), query);

            //根据不同参数据获取不同类型的数据
            if (MediaQuery.TYPE_HOME.equalsIgnoreCase(query.type)) {
                return returnHotMedia(query);
            } else if (MediaQuery.TYPE_DETAILS.equalsIgnoreCase(query.type)) {
                return getMediaDetails(query, null);
            } else if (MediaQuery.TYPE_SEARCH.equalsIgnoreCase(query.type)) {/**/
                //获取搜索
                return returnSearchMediaList(query);
            } else {
                //获取分类内容
                return returnMediaList(query);
            }
        }

        private void loggerOnQuery(Site site, MediaQuery query) {
            Logger.t(TAG).d(" --> 请求媒体信息 "
                    + "\n" + "site=" + site
                    + "\n" + "query=" + query);
        }

        /**
         * 详情
         *
         * @param query 查询选项。
         * @param bean  媒体对象。
         * @return 详情
         */
        @NonNull
        public MediaResult<List<MediaBean>> getMediaDetails(MediaQuery query, MediaBean bean) {
            Logger.t(TAG).d("--> get Media Details, query=" + query);
            try {
                String key = query.getSiteKey();
                String id = query.getId();
                Site site = VodConfig.get().getSite(key);
                if (site.getType() == 3) {//爬虫的
                    Spider spider = VodConfig.get().getSpider(site);
                    String detailContent = spider.detailContent(Collections.singletonList(id));
                    SpiderDebug.log(detailContent);
                    VodConfig.get().setRecent(site);
                    Logger.t(TAG).d("<-- get Media Details, " + detailContent);
                    return parseMediaJson(site, detailContent);
                } else if (site.isEmpty() && "push_agent".equals(key)) {//推送的
                    MediaBean vod = new MediaBean();
                    vod.setSiteKey(key);
                    vod.setVodId(id);
                    vod.setVodName(id);
                    vod.setVodPic("https://pic.rmb.bdstatic.com/bjh/1d0b02d0f57f0a42201f92caba5107ed.jpeg");
                    List<MediaBean> list = new ArrayList<>();
                    list.add(vod);
                    Logger.t(TAG).d("<-- get Media Details, " + list);
                    return MediaResult.success(bean, list);
                } else {
                    ArrayMap<String, String> params = new ArrayMap<>();
                    params.put("ac", site.getType() == 0 ? "videolist" : "detail");
                    params.put("ids", id);
                    String detailContent = call(site, params, true);
                    SpiderDebug.log(detailContent);
                    //将数据读取
                    Logger.t(TAG).d("<-- get Media Details, " + detailContent);
                    return parseMediaJson(site, detailContent);

                }
            } catch (Exception e) {
                e.printStackTrace();
                Logger.t("details").e("获取数据异常:" + e);
                return MediaResult.error(500).message("获取数据异常:" + e);
            }

        }

        private MediaResult<List<MediaBean>> returnMediaList(MediaQuery query) {
            Logger.t(TAG).d(" --> start return Media List. query=" + query);
            try {
                String siteKey = query.getSiteKey();
                if (siteKey == null) {
                    return MediaResult.error(400).message("siteKey is null");
                }

                Site site = VodConfig.get().getSite(siteKey);
                if (site == null) {
                    return MediaResult.error(400).message("site is null");
                }

                if (site.getType() == 3) {/*3从爬虫获取*/
                    MediaCallback.getDefault().onMessage("正在爬虫执行中");
                    Spider spider = VodConfig.get().getSpider(site);
                    String typeId = query.getId();
                    String page = String.valueOf(query.page());/*页码*/
                    boolean filter = query.isFilter();
                    HashMap<String, String> extend = (HashMap<String, String>) query.getExtend();

                    String categoryContent = spider.categoryContent(typeId, page, filter, extend);
                    MediaCallback.getDefault().onMessage("爬虫执行成功");
                    SpiderDebug.log(categoryContent);
                    return parseMediaJson(site, categoryContent);

                } else {/*从配置站源获取Json*/
                    MediaCallback.getDefault().onMessage("正在站源获取执行中");
                    String typeId = query.getId();//分类ID
                    String page = String.valueOf(query.page());
                    HashMap<String, String> extend = (HashMap<String, String>) query.getExtend();
                    ArrayMap<String, String> params = new ArrayMap<>();
                    if (site.getType() == 1 && !extend.isEmpty()) {
                        params.put("f", Init.json().toJson(extend));
                    } else if (site.getType() == 4) {
                        params.put("ext", Util.base64(Init.json().toJson(extend)));
                    }

                    params.put("ac", site.getType() == 0 ? "videolist" : "detail");
                    params.put("t", typeId);
                    params.put("pg", page);
                    String content = call(site, params, true);
                    MediaCallback.getDefault().onMessage("正在站源获取执行成功");
                    SpiderDebug.log(content);
                    if (site.getType() == 0) {
                        return parseMediaXML(site, content);
                    } else {
                        return parseMediaJson(site, content);
                    }

                }
            } catch (Exception e) {
                e.printStackTrace();
                Logger.t(TAG).e("获取数据异常:" + e);
                return MediaResult.error(500).message("获取数据异常:" + e);
            }
        }

        /**
         * 搜索媒体文件
         *
         * @param query 参数
         * @return MediaResult
         */
        @NonNull
        private MediaResult<List<MediaBean>> returnSearchMediaList(MediaQuery query) {
            Logger.t(TAG).d(" --> " +query );
            Logger.t(TAG).d(" --> Search Media List, query=" + query);
            try {
                Site site = VodConfig.get().getSite(query.getSiteKey());
                if (site == null) {
                    //尝试一次配置
                    return MediaResult.error(404).message("site为null");
                }

                if (site.getType() == 3) {/*3从爬虫获取*/
                    Spider spider = VodConfig.get().getSpider(site);
                    String keyword = query.getKeyword();
                    boolean quick = query.isQuick();
                    String page = String.valueOf(query.page());
                    String searchContent = "";
                    if (query.page() > 1) {
                        searchContent = spider.searchContent(Trans.t2s(keyword), false, page);
                    } else {
                        searchContent = spider.searchContent(Trans.t2s(keyword), quick);
                    }

                    Logger.t(TAG).d(" <-- " + searchContent);
                    Logger.t(TAG).d(" <-- " + query);
                    return parseMediaJson(site, searchContent);

                } else {/*从配置站源获取Json*/
                    String page = query.page() + "";
                    String keyword = query.getKeyword();
                    boolean quick = query.isQuick();
                    ArrayMap<String, String> params = new ArrayMap<>();
                    params.put("wd", Trans.t2s(keyword));
                    params.put("quick", String.valueOf(quick));
                    if (query.page() > 0) {
                        params.put("pg", page);
                    }
                    String searchContent = call(site, params, true);
                    Logger.t(TAG).d(" <-- " + searchContent);
                    Logger.t(TAG).d(" <-- " + query);
                    //解析数据
                    if (site.getType() == 0) {
                        //还需要获取图片
                        return parseMediaXML(site, searchContent);
                    } else {
                        return parseMediaJson(site, searchContent);
                    }
                }
            } catch (Exception e) {
                return MediaResult.error(500).message("获取数据异常:" + e);
            }

        }

        private MediaResult<List<MediaBean>> parseMediaXML(Site site, String response) {
            //TODO xml解析
            if (response == null) {
                MediaResult<List<MediaBean>> result = MediaResult.error(406).message("response is null");
                result.raw(response);/*源数据*/
                return result;
            }
            if (response.isEmpty()) {
                MediaResult<List<MediaBean>> result = MediaResult.error(405).message("response is Empty");
                result.raw(response);/*源数据*/
                return result;
            }
            JsonObject object = Json.parse(response).getAsJsonObject();
            List<MediaBean> list = new ArrayList<>();
            //获取媒分类内容（）
            for (JsonElement element : Json.safeListElement(object, "list")) {
                MediaBean item = MediaBean.objectFrom(element, site.getKey());
                list.add(item);
            }
            return MediaResult.success(response, list);
        }

        private MediaResult<List<MediaBean>> parseMediaJson(Site site, String response) {

            if (response == null) {
                MediaResult<List<MediaBean>> result = MediaResult.error(406).message("response is null");
                result.raw(response);/*源数据*/
                return result;
            }
            if (response.isEmpty()) {
                MediaResult<List<MediaBean>> result = MediaResult.error(405).message("response is Empty");
                result.raw(response);/*源数据*/
                return result;
            }
            JsonObject object = Json.parse(response).getAsJsonObject();
            MediaResult<List<MediaBean>> result = parseMediaJson(site, object);
            result.raw(response);/*源数据*/
            return result;
        }

        /**
         * @param site   相关源战点信息
         * @param object JsonObject
         * @return MediaResult
         */
        private MediaResult<List<MediaBean>> parseMediaJson(Site site, JsonObject object) {
            if (object == null) {
                return MediaResult.error(500).message("object is null");
            }
            List<MediaBean> list = new ArrayList<>();
            //获取媒分类内容（）
            for (JsonElement element : Json.safeListElement(object, "list")) {
                MediaBean item = MediaBean.objectFrom(element, site.getKey());
                list.add(item);
            }
            return MediaResult.success(list);
        }


        /**
         * 解析热点推荐　（豆辦）
         *
         * @param site     源站点
         * @param response String
         * @return MediaResult
         */
        private MediaResult<List<MediaBean>> parseHotMediaJson(Site site, String response) {
            JsonObject object = Json.parse(response).getAsJsonObject();
            List<MediaBean> list = new ArrayList<>();
            //获取推荐
            for (JsonElement element : Json.safeListElement(object, "data")) {
                MediaBean item = new MediaBean();
                JsonObject obj = element.getAsJsonObject();
                item.setVodName(Json.safeString(obj, "title"));
                item.setVodRemarks(Json.safeString(obj, "rate"));
                item.setVodPic(Json.safeString(obj, "cover"));
                item.setSiteKey(site.getKey());
                list.add(item);
            }

            return MediaResult.success(response, list);
        }

        /**
         * 获取推荐内容
         *
         * @param query MediaQuery
         * @return {@link MediaResult<List>}
         */
        private MediaResult<List<MediaBean>> returnHotMedia(MediaQuery query) {
            //#缓存
            try {
                Site site = VodConfig.get().getSite(query.getSiteKey());
                if (site == null) {
                    // 尝试一次配置
                    return MediaResult.error(400).message("site is null");
                }

                Calendar cal = Calendar.getInstance();
                int year = cal.get(Calendar.YEAR);
                int month = cal.get(Calendar.MONTH) + 1;
                int day = cal.get(Calendar.DATE);
                String today = String.format("%d%d%d", year, month, day);
                String requestDay = String.valueOf(Hawk.get("home_hot_day", ""));
                if (requestDay.equals(today)) {
                    String json = Hawk.get("home_hot", "");
                    SpiderDebug.log(json);
                    return parseHotMediaJson(site, json);
                }

                String content = OkHttp.string(getHotUrl());
                SpiderDebug.log(content);
                //缓存在本地(时间，内容）
                Hawk.put("home_hot_day", System.currentTimeMillis());
                Hawk.put("home_hot", content);
                return parseHotMediaJson(site, content);

            } catch (Exception e) {
                e.printStackTrace();
                Logger.t(TAG).e("获取数据异常:" + e);
                return MediaResult.error(500).message("获取数据异常:" + e);
            }

        }

        /**
         * 获取热点推荐API
         *
         * @return String
         */
        private String getHotUrl() {
            Calendar cal = Calendar.getInstance();
            int year = cal.get(Calendar.YEAR);
            return "https://movie.douban.com/j/new_search_subjects?sort=U&range=0,10&tags=&playable=1&start=0&year_range=" + year + "," + year;
        }

        private String call(Site site, ArrayMap<String, String> params, boolean limit) throws IOException {
            Call call = fetchExt(site, params, limit).length() <= 1000 ? OkHttp.newCall(site.getApi(), site.getHeaders(), params) : OkHttp.newCall(site.getApi(), site.getHeaders(), OkHttp.toBody(params));
            try (Response res = call.execute()) {
                if (res.body() != null) {
                    return res.body().string();
                } else {
                    // 处理 body 为空的情况
                    return null;
                }
            } catch (IOException e) {
                // 处理异常
                e.printStackTrace();
                return null;
            }
        }

        private String fetchExt(Site site, ArrayMap<String, String> params, boolean limit) throws IOException {
            String extend = site.getExt();
            if (extend.startsWith("http")) extend = fetchExt(site);
            if (limit && extend.length() > 1000) extend = extend.substring(0, 1000);
            if (!extend.isEmpty()) params.put("extend", extend);
            return extend;
        }

        private String fetchExt(Site site) throws IOException {
            Response res = OkHttp.newCall(site.getExt(), site.getHeaders()).execute();
            if (res.code() != 200) return "";
            site.setExt(res.body() != null ? res.body().string() : null);
            return site.getExt();
        }
    }
}
